#include "GlobalSettings.h"

using namespace erep;

/* PersonInfo */

PersonInfo::PersonInfo( const QString& id )
:   _state(0), _isMale(false), _fights(0), _damage(0), _lastExp(0)
{
    _id = id;
    for ( int i=0; i<4; ++i )
        _skills[i] = 0.0f;
    for ( int i=0; i<10; ++i )
        _mainProperties.push_back( QString() );
}

bool PersonInfo::parseJsonData( const QByteArray& array )
{
    QString data( array );
    int from = 0;
    _mainProperties[8] = findValue( data, "employer", &from );
    _mainProperties[2] = findValue( data, "wellness", &from );
    _party = findValue( data, "party", &from );
    _damage = findValue(data, "damage", &from).toUInt();
    _mainProperties[6] = findValue( data, "country", &from );
    _skills[3] = findValue(data, "strength", &from).toFloat();
    _mainProperties[9] = findValue( data, "employer_id", &from );
    _mainProperties[1] = findValue( data, "experience_points", &from );
    _mainProperties[6].prepend( findValue(data, "region", &from) + ", " );
    _mainProperties[0] = findValue( data, "level", &from );
    _fights = findValue(data, "fights", &from).toUInt();
    _isMale = findValue(data, "sex", &from).startsWith('M');
    _mainProperties[3] = findValue( data, "name", &from );
    _picture = findValue( data, "avatar_link", &from );
    _mainProperties[4] = findValue(data, "date_of_birth", &from).section('T', 0, 0);
    
    _skills[2] = findValue(data, "constructions\",\"value", 0, '\"', '}').toFloat();
    _skills[1] = findValue(data, "land\",\"value", 0, '\"', '}').toFloat();
    _skills[0] = findValue(data, "manufacturing\",\"value", 0, '\"', '}').toFloat();
    
    // Modify date
    int today = getErepDate( QDate::currentDate().toString("yyyy-MM-dd") );
    int currentExp = _mainProperties[1].toInt();
    if ( currentExp==_lastExp )
    {
        if ( !_mainProperties[5].isEmpty() )
        {
            int last = _mainProperties[5].remove(QObject::tr("Day")).toInt();
            int days = _mainProperties[7].toInt() + today - last;
            _mainProperties[7] = QString::number(days);
        }
    }
    else
    {
        _lastExp = currentExp;
        _mainProperties[7] = "0";
    }
    _mainProperties[5] = QString(QObject::tr("Day%1")).arg( today );
    _mainProperties[4] = QString(QObject::tr("Day%1")).arg( getErepDate(_mainProperties[4]) );
    return true;
}

bool PersonInfo::read( QTextStream& stream )
{
    QString line = stream.readLine();
    if ( line.isNull() ) return false;
    
    const char* SEP = "\",\"";
    int start = line.indexOf('\"')+1, end = line.lastIndexOf('\"');
    QStringList list = line.mid(start, end-start).split(SEP);
    if ( list.size()<22 ) return false;
    
    _state = list[0].toInt();
    _isMale = (list[1].toInt()!=0); _id = list[2];
    _picture = list[3]; _party = list[4];
    _fights = list[5].toUInt(); _damage = list[6].toUInt(); _lastExp = list[7].toUInt();
    for ( int i=0; i<4; ++i )
        _skills[i] = list[8+i].toFloat();
    for ( int i=0; i<10; ++i )
        _mainProperties[i] = list[12+i];
    return true;
}

bool PersonInfo::write( QTextStream& stream )
{
    const char* SEP = "\",\"";
    stream << '\"';
    stream << _state << SEP << _isMale << SEP << _id << SEP << _picture << SEP;
    stream << _party << SEP << _fights << SEP << _damage << SEP << _lastExp << SEP;
    for ( int i=0; i<4; ++i )
        stream << _skills[i] << SEP;
    for ( int i=0; i<9; ++i )
        stream << _mainProperties[i] << SEP;
    stream << _mainProperties[9] << '\"' << '\n';
    return true;
}

/* CompanyInfo */

CompanyInfo::CompanyInfo( const QString& id )
:   _quality(0)
{
    _id = id;
    for ( int i=0; i<4; ++i )
        _mainProperties.push_back( QString() );
}

bool CompanyInfo::parseJsonData( const QByteArray& array )
{
    QString data( array );
    int from = 0;
    _mainProperties[2] = findValue( data, "domain", &from );
    _mainProperties[1] = findValue( data, "country", &from );
    _quality = findValue(data, "quality", &from).toUInt();
    _mainProperties[3] = findValue( data, "industry", &from );
    _mainProperties[1].prepend( findValue(data, "region", &from) + ", " );
    _mainProperties[0] = findValue( data, "name", &from );
    return true;
}

bool CompanyInfo::read( QTextStream& stream )
{
    QString line = stream.readLine();
    if ( line.isNull() ) return false;
    
    const char* SEP = "\",\"";
    int start = line.indexOf('\"')+1, end = line.lastIndexOf('\"');
    QStringList list = line.mid(start, end-start).split(SEP, QString::SkipEmptyParts);
    if ( list.size()<6 ) return false;
    
    _id = list[0];
    _quality = list[1].toUInt();
    for ( int i=0; i<4; ++i )
        _mainProperties[i] = list[2+i];
    return true;
}

bool CompanyInfo::write( QTextStream& stream )
{
    const char* SEP = "\",\"";
    stream << '\"';
    stream << _id << SEP << _quality << SEP;
    for ( int i=0; i<3; ++i )
        stream << _mainProperties[i] << SEP;
    stream << _mainProperties[3] << '\"' << '\n';
    return true;
}

/* Global variables */

PersonInfoMap erep::globalCitizens;
CompanyInfoMap erep::globalCompanies;

/* Global functions */

int erep::getErepDate( const QString& date )
{
    static QDate erepBirth( 2007, 11, 21 );
    return erepBirth.daysTo( QDate::fromString(date, "yyyy-MM-dd") );
}

int erep::execDialog( const QString& text1, const QString& text2, QMessageBox::Icon icon,
                      const QString& btn1, const QString& btn2, const QString& btn3 )
{
    QMessageBox msgBox;
    msgBox.setText( text1 );
    msgBox.setInformativeText( text2 );
    msgBox.setIcon( icon );
    msgBox.addButton( btn1, QMessageBox::AcceptRole );
    if ( !btn2.isNull() ) msgBox.addButton( btn2, QMessageBox::RejectRole );
    if ( !btn3.isNull() ) msgBox.addButton( btn3, QMessageBox::DestructiveRole );
    return msgBox.exec();
}

QString erep::findValue( const QString& src, const QString& key, int* from, char sep, char sep2 )
{
    QString realKey( key );
    realKey.append( sep );
    int pos = src.indexOf( realKey, (from ? *from : 0) );
    if ( pos==-1 ) return QString();
    
    pos += realKey.length() + 1; // "key":
    int endpos = src.indexOf( sep, pos );
    if ( endpos==pos )  // there is a '\"' behind ':'
        endpos = src.indexOf( sep, ++pos );
    else
        endpos = src.indexOf( sep2, pos );
    
    if ( endpos!=-1 && from ) *from = endpos;
    return src.mid( pos, endpos-pos );
}

erep::PersonInfo* erep::findPerson( const QString& id )
{
    PersonInfoMap::iterator itr = globalCitizens.find(id);
    if ( itr!=globalCitizens.end() ) return itr.value();
    else return NULL;
}

erep::CompanyInfo* erep::findCompany( const QString& id )
{
    CompanyInfoMap::iterator itr = globalCompanies.find(id);
    if ( itr!=globalCompanies.end() ) return itr.value();
    else return NULL;
}

bool erep::openDataFile( const QString& filename )
{
    QFile file( filename );
    if ( !file.open(QIODevice::ReadOnly|QIODevice::Text) )
        return false;
    
    bool ok = true;
    QTextStream in( &file );
    int size = in.readLine().toInt();
    for ( int i=0; i<size; ++i )
    {
        PersonInfo* info = new PersonInfo( "" );
        ok &= info->read(in);
        if ( ok )
            globalCitizens[info->_id] = info;
    }
    
    size = in.readLine().toInt();
    for ( int i=0; i<size; ++i )
    {
        CompanyInfo* info = new CompanyInfo( "" );
        ok &= info->read(in);
        if ( ok )
            globalCompanies[info->_id] = info;
    }
    return ok;
}

bool erep::saveDataFile( const QString& filename, QTableWidget* refTable )
{
    int citizenSize = globalCitizens.size();
    int companySize = globalCompanies.size();
    if ( !citizenSize && !companySize ) return true;
    
    QStringList displayedPersons, displayedCompanies;
    if ( refTable )
    {
        // Collect displayed IDs
        for ( int i=0; i<refTable->rowCount(); ++i )
        {
            QTableWidgetItem* idItem = refTable->item(i, 1);   // Person ID
            QTableWidgetItem* coItem = refTable->item(i, 11);  // Company ID
            if ( idItem ) displayedPersons.push_back( idItem->text() );
            if ( coItem ) displayedCompanies.push_back( coItem->text() );
        }
        citizenSize = displayedPersons.size();
        companySize = displayedCompanies.size();
    }
    
    QFile file( filename );
    if ( !file.open(QIODevice::WriteOnly|QIODevice::Text) )
        return false;
    
    bool ok = true;
    QTextStream out( &file );
    out << citizenSize << '\n';
    for ( PersonInfoMap::iterator itr=globalCitizens.begin(); itr!=globalCitizens.end(); ++itr )
    {
        if ( refTable && displayedPersons.indexOf(itr.value()->_id)==-1 )
            continue;
        ok &= itr.value()->write(out);
    }
    
    out << companySize << '\n';
    for ( CompanyInfoMap::iterator itr=globalCompanies.begin(); itr!=globalCompanies.end(); ++itr )
    {
        if ( refTable && displayedCompanies.indexOf(itr.value()->_id)==-1 )
            continue;
        ok &= itr.value()->write(out);
    }
    return ok;
}
